package com.jdd.modules.sdk.sdkidentifycallbackresults;

import cn.hutool.core.collection.CollectionUtil;
import com.jdd.common.constant.CacheConstant;
import com.jdd.common.util.AsynRestTmplateUtils;
import com.jdd.common.util.CacheUtil;
import com.jdd.common.util.OssUtil;
import com.jdd.common.util.SnowFlakeUtil;
import com.jdd.common.util.excel.cache.manager.IFileLoader;
import com.jdd.modules.parkCarAbnormalRecord.entity.ParkCarAbnormalRecord;
import com.jdd.modules.parkCarAbnormalRecord.enums.AbnormalTypeEnums;
import com.jdd.modules.parkCarAbnormalRecord.service.IParkCarAbnormalRecordService;
import com.jdd.modules.parking.entity.ParkArmInfo;
import com.jdd.modules.parking.service.IParkArmInfoService;
import com.jdd.modules.sdk.config.CameraSdk;
import com.jdd.modules.sdk.utils.ZHENSHISDK;
import com.jdd.modules.sdkidentifyresultpushlog.entity.SdkIdentifyResultPushLog;

import com.jdd.modules.sdkidentifyresultpushlog.service.ISdkIdentifyResultPushLogService;
import com.jdd.modules.sdkidentifyresultpushlog.service.ISdkIdentifyResultPushLogV3Service;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;

/**
 * @version 1.0
 * @Description: 臻识相机识别结果回调
 * @author： jdd尚岳
 * @Date: 2021-07-29 17:20
 */
@Component
@Slf4j
public class ZhenShiSdkIdentifyCallbackResults implements ZHENSHISDK.VZLPRC_PLATE_INFO_CALLBACK {
    @Resource
    private ISdkIdentifyResultPushLogService sdkIdentifyResultPushLogService;

    @Resource
    private IParkArmInfoService parkArmInfoService;
    @Resource
    CameraSdk cameraSdk;
    @Resource
    AsynRestTmplateUtils asynRestTmplateUtils;
    @Value("${oss.domain.name}")
    private String ossDomainName;
    @Value("${uploadImages.location}")
    private String imageLocation;
    @Value("${uploadFile.location}")
    private String location;
    @Resource
    private CacheUtil cacheUtil;
    @Resource
    private OssUtil ossUtil;
    @Resource
    private IParkCarAbnormalRecordService parkCarAbnormalRecordService;
    @Autowired
    private ISdkIdentifyResultPushLogV3Service sdkIdentifyResultPushLogV3Service;
    @Override
    public void invoke(long handle, Pointer pUserData, ZHENSHISDK.TH_PlateResult_Pointer.ByReference pResult, int uNumPlates, int eResultType, ZHENSHISDK.VZ_LPRC_IMAGE_INFO_Pointer.ByReference pImgFull, ZHENSHISDK.VZ_LPRC_IMAGE_INFO_Pointer.ByReference pImgPlateClip) throws UnknownHostException, Exception {
        int type = ZHENSHISDK.VZ_LPRC_RESULT_TYPE.VZ_LPRC_RESULT_REALTIME.ordinal();
        if (eResultType != type) {
            log.info("=======进入识别区域==========");
            // 根据设备句柄，获取当前回调结果设备的IP
            byte[] device_ip = new byte[32];
            cameraSdk.zhenshiSdk.VzLPRClient_GetDeviceIP(handle, device_ip, 32);
            String ip = new String(device_ip);
            log.info("=======获取设备IP==========");
            //如果出入场车场配置为null，则说明车场有问题提前返回
            ParkArmInfo parkArmInfo = parkArmInfoService.findParkArmInfoByIp(ip.trim());
            if (null == parkArmInfo) {
                return;
            }

            byte[] bytes = new byte[16];
            long startTime = System.currentTimeMillis();
            log.info("=======开始解密==========-》{}", startTime);
            // 获取方法运行时间
            int i = cameraSdk.zhenshiSdk.VzLPRClient_AesCtrDecrypt(pResult.license, 16, "jddHLW966", bytes, 16);
            Long endTime = System.currentTimeMillis() - startTime;
            log.info("=======解密消耗时间==========-》{}", endTime);
            SdkIdentifyResultPushLog sdkIdentifyResultPushLog = new SdkIdentifyResultPushLog();

            //获取车牌号信息
            String license = new String(bytes, "gb2312");
            if (license.contains("港") || license.contains("澳")) {
                //N系列一体机甄识相机识别港澳多出来几位
                license = license.substring(0, 7);
            }
            if (license.contains("无")){
                license="无牌车";
             }
             sdkIdentifyResultPushLog.setId(SnowFlakeUtil.getId());
            sdkIdentifyResultPushLog.setParkCode(parkArmInfo.getParkCode());
            sdkIdentifyResultPushLog.setParkName(parkArmInfo.getParkName());
            sdkIdentifyResultPushLog.setSerialNo(parkArmInfo.getSerialNo());
            sdkIdentifyResultPushLog.setLicense(license.trim());
            sdkIdentifyResultPushLog.setNTime(pResult.tvPTS.uTVSec);
            sdkIdentifyResultPushLog.setCreateTime(new Date());
            sdkIdentifyResultPushLog.setNType(pResult.nType);
            sdkIdentifyResultPushLog.setColor(byteArray2Int(pResult.color));
            //保存图片
            log.info("==========保存图片开始时间============->{}", System.currentTimeMillis());
            mkdirsAndSavePic(pImgPlateClip, sdkIdentifyResultPushLog, pResult, pImgFull);
            log.info("==========保存图片结束时间============->{}", System.currentTimeMillis());

            sdkIdentifyResultPushLogService.save(sdkIdentifyResultPushLog);
            //获取应急开闸序列号
            String emergencyOpeningSerialNo = cacheUtil.get(CacheConstant.EMERGENCY_OPENING_SERIALNO_NAME, CacheConstant.EMERGENCY_OPENING_SERIALNO_KEY);
            if (StringUtils.isNotBlank(emergencyOpeningSerialNo)
                    && eResultType == ZHENSHISDK.VZ_LPRC_RESULT_TYPE.VZ_LPRC_RESULT_FORCE_TRIGGER.ordinal()) {
                //如果为应急开闸，保存异常记录并不走下面的出入场逻辑
                parkCarAbnormalRecordService.saveAbnormalRecord(sdkIdentifyResultPushLog, parkArmInfo, AbnormalTypeEnums.EMERGENCY_OPENING);
                cacheUtil.delete(CacheConstant.EMERGENCY_OPENING_SERIALNO_NAME, CacheConstant.EMERGENCY_OPENING_SERIALNO_KEY);
                return;
            }
            //获取遥控开闸序列号
            String emotePenedSerialNo = cacheUtil.get(CacheConstant.EMOTE_PENED, parkArmInfo.getSerialNo());
            if (StringUtils.isNotBlank(emotePenedSerialNo)&& eResultType == ZHENSHISDK.VZ_LPRC_RESULT_TYPE.VZ_LPRC_RESULT_FORCE_TRIGGER.ordinal()) {
                //根据识别的车牌号获取最近的一条入场纪录的
                parkCarAbnormalRecordService.saveRemoteControlAbnormalRecord(sdkIdentifyResultPushLog, parkArmInfo, AbnormalTypeEnums.REMOTE_CONTROL_OPENING);
                cacheUtil.delete(CacheConstant.EMOTE_PENED, parkArmInfo.getSerialNo());
                cacheUtil.delete(CacheConstant.CURRENT_EXIT_LICENSE_PLATE, parkArmInfo.getSerialNo());
                return;
            }
            // 第三版出入场逻辑调用
            sdkIdentifyResultPushLogV3Service.identifyJudge(sdkIdentifyResultPushLog, parkArmInfo);
        }
    }

    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    /**
     * @param b
     * @return
     * @Description byte数组转换为整型
     * @author shangyue
     * @Date 2021/4/6
     */
    public static int byteArray2Int(byte[] b) {
        int value = 0;
        for (int i = b.length - 1; i >= 0; i--) {
            int shift = (b.length - 1 - i) * 8;
            value += (b[i] & 0x000000FF) << shift;
        }

        return value;
    }


    /**
     * 字符串转化成为16进制字符串
     *
     * @param s
     * @return
     */
    public static String strTo16(String s) {
        String str = "";
        for (int i = 0; i < s.length(); i++) {
            int ch = (int) s.charAt(i);
            String s4 = Integer.toHexString(ch);
            str = str + s4;
        }
        return str;
    }

    /*
     * @author lcy
     * @date 2021/8/21
     * @Description 本地生成文件夹保存图片并上传到oss
     */
    public void mkdirsAndSavePic(ZHENSHISDK.VZ_LPRC_IMAGE_INFO_Pointer.ByReference pImgPlateClip, SdkIdentifyResultPushLog sdkIdentifyResultPushLog, ZHENSHISDK.TH_PlateResult_Pointer.ByReference pResult, ZHENSHISDK.VZ_LPRC_IMAGE_INFO_Pointer.ByReference pImgFull) {
        String ossImg = null;
        //抓拍时间,每天一个文件夹
        Calendar instance = Calendar.getInstance();
        int year = instance.get(Calendar.YEAR);
        int month = instance.get(Calendar.MONTH) + 1;
        int day = instance.get(Calendar.DAY_OF_MONTH);
        //文件夹名字生成规则请勿轻易更改，如果更改，请修改定时删除图片任务的文件夹名字的生成规则
        String imgUrl = imageLocation + "/" + year + "-" + month + "-" + day;
        File dir = new File(imgUrl);
        // 判断目录是否存在
        if (!dir.exists()) {
            boolean b = dir.mkdirs();
            System.out.println(b);
        }
        //随机生成6位随机数
        Random random = new Random();
        String result = "";
        for (int i = 0; i < 6; i++) {
            result += random.nextInt(10);
        }
        Integer time = pResult.struBDTime.bdt_year + pResult.struBDTime.bdt_mon
                + pResult.struBDTime.bdt_mday + pResult.struBDTime.bdt_hour
                + pResult.struBDTime.bdt_min + pResult.struBDTime.bdt_sec;

        //图片存放路径
        //文件夹名字生成规则请勿轻易更改，如果更改，请修改定时删除图片任务的文件夹名字的生成规则
        String impart = imgUrl + File.separator + time + sdkIdentifyResultPushLog.getSerialNo() +result + ".jpg";
        //小车牌图片
        String imparts = imgUrl + File.separator + time + "car" + result + ".jpg";

        //将图片保存到指定的位置
        sdkIdentifyResultPushLog.setPlateNoImg(imparts);
        //车牌图片
        cameraSdk.zhenshiSdk.VzLPRClient_ImageSaveToJpeg(pImgPlateClip, imparts.trim(), 50);

        cameraSdk.zhenshiSdk.VzLPRClient_ImageSaveToJpeg(pImgFull, impart.trim(), 50);

        impart = location + "/" + year + "-" + month + "-" + day + File.separator + time + sdkIdentifyResultPushLog.getSerialNo() + result + ".jpg";

        sdkIdentifyResultPushLog.setImg(impart);

        String getOssUrl = ossUtil.getImgUrl();

        sdkIdentifyResultPushLog.setOssImg(ossDomainName+getOssUrl);

        asynRestTmplateUtils.uploadOssImg(impart,getOssUrl);

    }
}
